package fr.inserm.u915.tabixserver.expr;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.net.URLEncoder;
import java.util.List;

public abstract class ExprNode {
	protected ExprNode()
	    {
	    }

	public abstract ExprNode eval(Context ctx);
	
	
	static class IntNode extends ExprNode
	     {
	     private BigInteger value;
	     public IntNode(String value)
	           {
	           this.value=new BigInteger(value);
	           }
	    
	     @Override
	     public ExprNode eval(Context ctx)
	         {
	         return this;
	         }
	    
	     public String toString()
	         {
	         return this.value.toString();
	         }
	     }
	 
	 static class FloatNode extends ExprNode
	     {
	     private BigDecimal value;
	     public FloatNode(String value)
	           {
	           this.value=new BigDecimal(value);
	           }
	    
	     @Override
	     public ExprNode eval(Context ctx)
	         {
	         return this;
	         }
	    
	     public String toString()
	         {
	         return this.value.toString();
	         }
	     }

	  static class StringNode extends ExprNode
	     {
	     private String value;
	     public StringNode(String value)
	           {
	           this.value=value;
	           }
	    
	     @Override
	     public ExprNode eval(Context ctx)
	         {
	         return this;
	         }
	     @Override
	     public String toString()
	         {
	         return value;
	         }
	     }
	
	 static class ColRefNode extends ExprNode
	     {
	     private String colName;
	     public ColRefNode(String colName)
	           {
	           this.colName=colName;
	           }
	     @Override
	     public ExprNode eval(Context ctx)
	         {
	         String s= ctx.get(colName);
	         return s==null? null : new StringNode(s);
	         }
	     @Override
	     public String toString()
	         {
	         return "$"+colName;
	         }
	     }
	
	 static class FunNode extends ExprNode
	     {
	     private String funName;
	     private List<ExprNode> nodes;
	     public FunNode(String funName,List<ExprNode> nodes)
	           {
	           this.funName=funName;
	           this.nodes=nodes;
	           }
	     @Override
	     public ExprNode eval(Context ctx)
	         {
	         if(funName.equals("concat"))
	             {
	             StringBuilder b=new StringBuilder();
	             for(int i=0;i<  nodes.size();++i)
	                 {
	            	 ExprNode n=nodes.get(i).eval(ctx);
	                 if(n==null) continue;
	                 b.append(String.valueOf(n));
	                 }
	             return new StringNode(b.toString());
	             }
	         else if(funName.equals("build") && nodes.isEmpty())
	             {
	             return new StringNode(ctx.getInstance().getBuild().getId());
	             }
	         else if(funName.equals("instance") && nodes.isEmpty())
	             {
	             return new StringNode(ctx.getInstance().getId());
	             }
	         else if(funName.equals("table") && nodes.isEmpty())
	             {
	             return new StringNode(ctx.getInstance().getTable().getId());
	             }
	         else if(funName.equals("url-escape") && !nodes.isEmpty())
	             {
	             try {
	            	 ExprNode n=nodes.get(0).eval(ctx);
	                 if(n==null) return null;
	            	 return new StringNode(URLEncoder.encode(
	            			 String.valueOf(n)
	            			 , "UTF-8")
	            			 );
	             	} 
	             catch (Exception e)
	             	{
	            	return null;
					}
	             }
	         return null;
	         }
	
	     public String toString()
	         {
	         return funName;
	         }
	     }
	}
